package com.yunban.project.message.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tencentcloudapi.sms.v20190711.models.SendStatus;
import com.yunban.project.message.domain.SmsRecord;
import com.yunban.project.message.mapper.SmsRecordMapper;
import com.yunban.project.message.service.SmsService;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20190711.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20190711.models.SendSmsResponse;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.base.common.exception.BusinessException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.tencentcloudapi.sms.v20190711.SmsClient;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Collections;

/**
 * @author: lijiajun
 * @date: 2025-03-07
 * @version: 1.0
 */
@Slf4j
@Service
public class SmsServiceImpl extends ServiceImpl<SmsRecordMapper, SmsRecord> implements SmsService {

    @Value("${tencent.sms.secret-id}")
    private String secretId;
    @Value("${tencent.sms.secret-key}")
    private String secretKey;
    @Value("${tencent.sms.endpoint}")
    private String endpoint;
    @Value("${tencent.sms.region}")
    private String region;
    @Value("${tencent.sms.appid}")
    private String appid;
    @Value("${tencent.sms.sign-name}")
    private String signName;
    @Value("${tencent.sms.template-id}")
    private String templateId;

    private final static int DESIRED_MINUTES_LIMIT = 300;

    @Override
    public Boolean send(String code, String phoneNo) {
        //检查是否是重复发送
        this.checkRepeatSend(phoneNo);
        Credential cred = new Credential(secretId, secretKey);
        // 实例化一个http选项
        HttpProfile httpProfile = new HttpProfile();
        httpProfile.setReqMethod(HttpProfile.REQ_POST);
        httpProfile.setConnTimeout(60);
        httpProfile.setEndpoint(endpoint);
        // 实例化一个客户端配置对象，可以指定超时时间等配置
        ClientProfile clientProfile = new ClientProfile();
        // SDK默认用TC3-HMAC-SHA256进行签名  必要请不要修改这个字段
        clientProfile.setSignMethod("HmacSHA256");
        clientProfile.setHttpProfile(httpProfile);
        SmsClient client = new SmsClient(cred, region, clientProfile);
        SendSmsRequest request = new SendSmsRequest();
        request.setSmsSdkAppid(appid);
        request.setSign(signName);
        request.setTemplateID(templateId);
        String[] templateParamSet = {code, "5"};
//        String[] templateParamSet = {code};
        request.setTemplateParamSet(templateParamSet);
        log.info("phoneNo:{}", phoneNo);
        request.setPhoneNumberSet(Collections.singletonList("86" + phoneNo).toArray(new String[0]));
        SendSmsResponse res;
        log.info("request:{}", JSON.toJSONString(request));
        String message = "";
        try {
            res = client.SendSms(request);
            SendStatus[] sendStatusSet = res.getSendStatusSet();
            for (SendStatus sendStatus : sendStatusSet) {
                message = sendStatus.getMessage();
            }
            log.info("send sms res: {}", SendSmsResponse.toJsonString(res));
        } catch (TencentCloudSDKException e) {
            log.error("send sms error", e);
            log.error("send sms error: {}", e.getMessage());
            throw new BusinessException("send sms error:" + e.getMessage());
        }
        // 入库
        this.saveSmsLog(code, phoneNo, message);
        return true;
    }

    @Override
    public SmsRecord getLastSendRecord(String phoneNo) {
        LambdaQueryWrapper<SmsRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SmsRecord::getPhoneNo, phoneNo);
        wrapper.orderByDesc(SmsRecord::getId);
        wrapper.last("limit 1");
        return this.getOne(wrapper);
    }

    @Override
    public void saveSmsLog(String code, String phoneNo, String message) {
        SmsRecord record = new SmsRecord();
        record.setCode(code);
        record.setPhoneNo(phoneNo);
        record.setMessage(message);
        record.setExpiredAt(LocalDateTime.now().plusSeconds(DESIRED_MINUTES_LIMIT));
        this.save(record);
    }

    @Override
    public void checkCode(String phoneNo, String code) {
        SmsRecord lastRecord = this.getLastSendRecord(phoneNo);
        if (ObjectUtils.isEmpty(lastRecord)) {
            throw new BusinessException("验证码有误");
        }
        if (lastRecord.getExpiredAt().isBefore(LocalDateTime.now())) {
            throw new BusinessException("验证码已过期，请重新获取");
        }
        // 检查验证码是否已经被使用
        if (lastRecord.isUsed()) {
            throw new BusinessException("验证码已被使用，请重新获取");
        }
        // 从数据库记录中提取实际验证码，假设记录的格式是 ["100001"]
        // 去除方括号
        String dbCode = lastRecord.getCode();
//        String dbCode = lastRecord.getCode().replace("[", "").replace("]", ""); // 去除方括号
        if (!dbCode.equals(code)) {
            throw new BusinessException("验证码错误");
        }
        // 使用验证码
        lastRecord.setUsed(true);
        this.updateById(lastRecord);
    }

    @Override
    public void checkRepeatSend(String phoneNo) {
        SmsRecord lastRecord = this.getLastSendRecord(phoneNo);
        if (ObjectUtils.isEmpty(lastRecord)) {
            return;
        }
        long secondsSinceLastSend = ChronoUnit.SECONDS.between(lastRecord.getCreatedAt(), LocalDateTime.now());
        if (secondsSinceLastSend < 60) {
            throw new BusinessException("请勿在一分钟内频繁请求验证码");
        }
    }
}
